/**
  ******************************************************************************
  * File Name          : measure.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention : 注意单位!!! 
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "bsp.h"
#include "tskcfg.h"
#include "measure.h"
#include "parameter.h"
#include <stdlib.h>
#include "gui.h"

static inline void meas_azero_init(GlobalVariablesStru *pgv)
{
  pgv->ir.meas_ca.autozero_zero_adjust = 0;
  pgv->ir.meas_ca.autozero_elapsed_time_0d01s = 0;
  pgv->ir.meas_ca.autozero_elapsed_pulse = 0;
  pgv->ir.meas_ca.autozero_elapsed_adcnt = 0;
  pgv->ir.meas_ca.autozero_wad_add = 0;
}

void meas_auto_zero(GlobalVariablesStru *pgv)
{
  uint64_t belt_len_pulse;
  int32_t temp;
  float ppl_0d1mm; /* 单位长度的脉冲数 */
  float belt_elapsed_len_0d1mm;

  pgv->ir.meas_ca.autozero_elapsed_time_0d01s++;                      /* 流逝的时间,以0.1s为单位 */
  pgv->ir.meas_ca.autozero_elapsed_adcnt++;                           /* 累加AD转换的次数 */
  pgv->ir.meas_ca.autozero_wad_add += pgv->ir.meas_ad.wad_unified;                /* 累加重量AD信号 */
  pgv->ir.meas_ca.autozero_elapsed_pulse += pgv->ir.meas_ad.sad_100hz;    /* 累加速度脉冲数 */

  if(pgv->hr.meas_pa.len_circle_mode == MEAS_LEN_CIRCLE_FIXLENG)
  {
    /* 定长模式下,当皮带运行过的长度等于皮带周长时,完成一次零点计算 */
    ppl_0d1mm = (float)pgv->hr.meas_pa.speed_wheel_pls / (float)pgv->hr.meas_pa.speed_wheel_cir_0d1mm;  /* 计算单位长度(0.1mm)的脉冲数 */
    belt_len_pulse = ((float)pgv->hr.meas_pa.belt_length_mm * 10.0) * ppl_0d1mm;                    /* 计算皮带整长所需脉冲数 */

    if(pgv->ir.meas_ca.autozero_elapsed_pulse >= belt_len_pulse)
    {
      pgv->ir.meas_ca.autozero_zero_adjust = pgv->ir.meas_ca.autozero_wad_add / pgv->ir.meas_ca.autozero_elapsed_adcnt;
      pgv->ir.meas_ca.autozero_elapsed_time_0d01s = 0;
      pgv->ir.meas_ca.autozero_elapsed_pulse = 0;
      pgv->ir.meas_ca.autozero_elapsed_adcnt = 0;
      pgv->ir.meas_ca.autozero_wad_add = 0;
      
      temp = abs(pgv->ir.meas_ca.autozero_zero_adjust - pgv->hr.meas_pa.zero_code_ave);
      
      /* 如果本次零点与当前零点的差值在允许的范围内,且不大于零点上限,调零成功 */
      if((pgv->ir.meas_ca.autozero_zero_adjust <= pgv->hr.meas_pa.zero_code_uplimit) && (temp != 0) && (temp <= pgv->hr.meas_pa.auto_zero_range))
      {
        /* 更新零点内码参数 */
      }
    }
  }
  else
  {
    /* 定时模式下,当皮带运行过的时间等于皮带周期时,完成一次零点计算 */
    if(pgv->ir.meas_ca.autozero_elapsed_time_0d01s >= pgv->hr.meas_pa.belt_period_0d01s)
    {
      pgv->ir.meas_ca.autozero_zero_adjust = pgv->ir.meas_ca.autozero_wad_add / pgv->ir.meas_ca.autozero_elapsed_adcnt;
      pgv->ir.meas_ca.autozero_elapsed_time_0d01s = 0;
      pgv->ir.meas_ca.autozero_elapsed_pulse = 0;
      pgv->ir.meas_ca.autozero_elapsed_adcnt = 0;
      pgv->ir.meas_ca.autozero_wad_add = 0;

      temp = abs(pgv->ir.meas_ca.autozero_zero_adjust - pgv->hr.meas_pa.zero_code_ave);

      /* 如果本次零点与当前零点的差值在允许的范围内,且不大于零点上限,调零成功 */
      if((pgv->ir.meas_ca.autozero_zero_adjust <= pgv->hr.meas_pa.zero_code_uplimit) && (temp != 0) && (temp <= pgv->hr.meas_pa.auto_zero_range))
      {
        /* 更新零点内码参数 */
      }
    }
  }
}

static inline void meas_mzero_init(GlobalVariablesStru *pgv)
{
  pgv->ir.meas_ca.calmzero_elapsed_belt_cnt = 0;
  pgv->ir.meas_ca.calmzero_zero_adjust1 = 0;
  pgv->ir.meas_ca.calmzero_zero_adjust2 = 0;
  pgv->ir.meas_ca.calmzero_belt_remainder_mm = 0;
  pgv->ir.meas_ca.calmzero_belt_remainder_0d01s = 0;
  pgv->ir.meas_ca.calmzero_elapsed_time_0d01s = 0;
  pgv->ir.meas_ca.calmzero_elapsed_pulse = 0;
  pgv->ir.meas_ca.calmzero_elapsed_adcnt = 0;
  pgv->ir.meas_ca.calmzero_wad_add = 0;
  
  pgv->ir.meas_ca.calibrate_timeout = 0;

  pgv->co.meas_ec.manual_zero_save_key = 0;

  pgv->di.meas_is.calzero_msg = 0;
}

static inline Meas_ReturnEnum meas_mzero_process(GlobalVariablesStru *pgv)
{
  uint64_t belt_len_pulse;
  int32_t temp;
  float ppl_0d1mm; /* 单位长度的脉冲数 */
  float belt_elapsed_len_0d1mm;

  pgv->ir.meas_ca.calmzero_elapsed_time_0d01s++;                          /* 流逝的时间,以0.1s为单位 */
  pgv->ir.meas_ca.calmzero_elapsed_adcnt++;                               /* 累加AD转换的次数 */
  pgv->ir.meas_ca.calmzero_wad_add += pgv->ir.meas_ad.wad_unified;                /* 累加重量AD信号 */
  pgv->ir.meas_ca.calmzero_elapsed_pulse += pgv->ir.meas_ad.sad_100hz;    /* 累加速度脉冲数 */

  if(pgv->hr.meas_pa.len_circle_mode == MEAS_LEN_CIRCLE_FIXLENG)
  {
    /* 转小单位来保证精度不丢失(或用浮点算),否则皮带越长,丢失的精度越多 */
    ppl_0d1mm = (float)pgv->hr.meas_pa.speed_wheel_pls / (float)pgv->hr.meas_pa.speed_wheel_cir_0d1mm;    /* 计算单位长度(0.1mm)的脉冲数 */
    belt_len_pulse = ((float)pgv->hr.meas_pa.belt_length_mm * 10.0) * ppl_0d1mm;                          /* 计算皮带整长所需脉冲数 */
    
    belt_elapsed_len_0d1mm = (float)pgv->ir.meas_ca.calmzero_elapsed_pulse / ppl_0d1mm;                  /* 计算皮带转过的长度 */
    pgv->ir.meas_ca.calmzero_belt_remainder_mm = pgv->hr.meas_pa.belt_length_mm - (belt_elapsed_len_0d1mm / 10.0); /* 计算皮带剩余的长度 */

    if(pgv->ir.meas_ca.calmzero_elapsed_pulse >= belt_len_pulse)                                         /* 定长模式下,当皮带运行过的长度等于皮带周长时,完成一次零点计算 */
    {
      pgv->ir.meas_ca.calmzero_elapsed_belt_cnt++;                                                       /* TODO: 设一个上限,超过上限调零失败,否则会无限循环下去 */
      pgv->ir.meas_ca.calmzero_zero_adjust1 = pgv->ir.meas_ca.calmzero_wad_add / pgv->ir.meas_ca.calmzero_elapsed_adcnt; /* 算得校验以来的平均重量内码 */
      
      /* 一圈跑完后,清除变量,重新开始跑 */
      pgv->ir.meas_ca.calmzero_elapsed_pulse = 0;
      pgv->ir.meas_ca.calmzero_elapsed_adcnt = 0;
      pgv->ir.meas_ca.calmzero_wad_add = 0;
      
      temp = abs(pgv->ir.meas_ca.calmzero_zero_adjust1 - pgv->ir.meas_ca.calmzero_zero_adjust2);
      
      /* 如果两次零点的差值在允许的范围内,且均不大于零点上限,调零成功 */
      if((pgv->ir.meas_ca.calmzero_zero_adjust1 <= pgv->hr.meas_pa.zero_code_uplimit) && \
         (pgv->ir.meas_ca.calmzero_zero_adjust2 <= pgv->hr.meas_pa.zero_code_uplimit) && \
         (temp <= pgv->hr.meas_pa.manu_zero_range))
      {
        /* 调零成功后,切换仪表进入调零完成状态 */
        return RET_SUCCESS;
      }
      else
      {
        pgv->ir.meas_ca.calmzero_zero_adjust2 = pgv->ir.meas_ca.calmzero_zero_adjust1;
        /* 继续 再来一圈 */
      }
    }
  }
  else /* 定时模式下,当皮带运行过的时间等于皮带周期时,完成一次零点计算 */
  {
    pgv->ir.meas_ca.calmzero_belt_remainder_0d01s = pgv->hr.meas_pa.belt_period_0d01s - pgv->ir.meas_ca.calmzero_elapsed_time_0d01s;
    
    if(pgv->ir.meas_ca.calmzero_elapsed_time_0d01s >= pgv->hr.meas_pa.belt_period_0d01s)
    {
      pgv->ir.meas_ca.calmzero_elapsed_belt_cnt++;
      pgv->ir.meas_ca.calmzero_zero_adjust1 = pgv->ir.meas_ca.calmzero_wad_add / pgv->ir.meas_ca.calmzero_elapsed_adcnt;
      
      if((pgv->ir.meas_ca.calmzero_wad_add % pgv->ir.meas_ca.calmzero_elapsed_adcnt) * 2 >= pgv->ir.meas_ca.calmzero_elapsed_adcnt)
      {
        pgv->ir.meas_ca.calmzero_zero_adjust1++;
      }
      
      pgv->ir.meas_ca.calmzero_elapsed_time_0d01s = 0;
      pgv->ir.meas_ca.calmzero_elapsed_adcnt = 0;
      pgv->ir.meas_ca.calmzero_wad_add = 0;
      
      temp = abs(pgv->ir.meas_ca.calmzero_zero_adjust1 - pgv->ir.meas_ca.calmzero_zero_adjust2);
      
      /* 如果两次零点的差值在允许的范围内,且均不大于零点上限,调零成功 */
      if((pgv->ir.meas_ca.calmzero_zero_adjust1 <= pgv->hr.meas_pa.zero_code_uplimit) && 
         (pgv->ir.meas_ca.calmzero_zero_adjust2 <= pgv->hr.meas_pa.zero_code_uplimit) && 
         (temp <= pgv->hr.meas_pa.manu_zero_range))
      {
        /* 调零成功后,切换仪表进入调零完成状态 */
        return RET_SUCCESS;
      }
      else
      {
        pgv->ir.meas_ca.calmzero_zero_adjust2 = pgv->ir.meas_ca.calmzero_zero_adjust1;
        /* 继续 再来一圈 */
      }
    }
  }

  return RET_RUNNING;
}

static Meas_ReturnEnum meas_mzero_waitsave(GlobalVariablesStru *pgv)
{    
  if(pgv->co.meas_ec.manual_zero_save_key == 1) /* 确认保存 */
  {
    pgv->co.meas_ec.manual_zero_save_key = 0;

    sto_update_item(sto_mtidx(zero_code_ave), (const Sto_CellUnion *)&pgv->ir.meas_ca.calmzero_zero_adjust1, 5);

    pgv->ir.meas_ca.calibrate_timeout = 0;

    return RET_SUCCESS;
  }

  if(pgv->ir.meas_ca.calibrate_timeout++ >= MEAS_CALIBRATE_WATI_SAVE_TIMEOUT)  /* 等待超时 */
  {
    return RET_FAIL;
  }

  return RET_RUNNING;
}

static inline void meas_mzero_exit(GlobalVariablesStru *pgv)
{
  pgv->ir.meas_ca.calibrate_timeout = 0;
}

Meas_ReturnEnum meas_manual_zero(GlobalVariablesStru *pgv)
{
  uint8_t res;
  Meas_ReturnEnum ret;
  Gui_CmdQueStru scmd;

  ret = RET_RUNNING;

  if(pgv->co.meas_ec.manual_zero_stop_key == 1)
  {
    pgv->co.meas_ec.manual_zero_stop_key = 0;
    pgv->ir.meas_ca.calmzero_substmachine = MZERO_SUB_STATE_MACHINE_SENDMSG;
    pgv->di.meas_is.calzero_msg = 1;
  }

  switch(pgv->ir.meas_ca.calmzero_substmachine)
  {
    case MZERO_SUB_STATE_MACHINE_INIT:
      meas_mzero_init(pgv);
      pgv->ir.meas_ca.calmzero_substmachine = MZERO_SUB_STATE_MACHINE_PROCESS;

    case MZERO_SUB_STATE_MACHINE_PROCESS:
      res = meas_mzero_process(pgv);
      if(res == RET_SUCCESS)
      {
        pgv->ir.meas_ca.calmzero_substmachine = MZERO_SUB_STATE_MACHINE_WAITSAVE;
        xQueueSend(gui_cmd_qhd, &gui_cmd_go_calzeroend, 2);   /* 切换校验完成页面 */
      }
      else if(res == RET_FAIL)
      {
        pgv->ir.meas_ca.calmzero_substmachine = MZERO_SUB_STATE_MACHINE_SENDMSG;
        pgv->di.meas_is.calzero_msg = 2;
        break;
      }
      else
      {
        break; /* go on */
      }

    case MZERO_SUB_STATE_MACHINE_WAITSAVE:
      res = meas_mzero_waitsave(pgv);
      if(res == RET_SUCCESS)
      {
        pgv->ir.meas_ca.calmzero_substmachine = MZERO_SUB_STATE_MACHINE_SENDMSG;
        pgv->di.meas_is.calzero_msg = 3;
      }
      else if(res == RET_FAIL)
      {
        pgv->ir.meas_ca.calmzero_substmachine = MZERO_SUB_STATE_MACHINE_SENDMSG;
        pgv->di.meas_is.calzero_msg = 4;
      }
      else
      {
        break; /* go on */
      }

    case MZERO_SUB_STATE_MACHINE_SENDMSG:
      pgv->ir.meas_ca.calmzero_substmachine = MZERO_SUB_STATE_MACHINE_EXIT;
      scmd.cmd = GUI_CMD_CHANGE_FORM;
      scmd.key = IRKEY_KEY_VALUE_NULL;
      scmd.toform = &gui_from_calmessage;
      scmd.msg = pgv->di.meas_is.calzero_msg;
      xQueueSend(gui_cmd_qhd, &scmd, 2);

    default:
    case MZERO_SUB_STATE_MACHINE_EXIT:
      meas_mzero_exit(pgv);
      return RET_EXIT;
  }

  return ret;
}
